// 
const WHITESPACE = /(\s|\t|\n|\r)/;
const NUMBERS = /[0-9]/;
const NAME = /[0-9a-zA-Z_\.]/;

function lexer(input) {
    let tokens = [];
    let current = 0;
    let inTag = false;
    let char = "";
    while (current < input.length) {
        char = input[current];
        // 检查空格
        if (WHITESPACE.test(char)) {
            current = current + 1;
            continue;
        }

        const getToken = function (regex) {
            let value = '';
            while (regex.test(char) && current < input.length) {
                value += char;
                current = current + 1;
                char = input[current];
            }
            return value;
        }

        const getCode = () => {
            let code = '';
            let braceCount = 1;
            while (braceCount > 0 && current < input.length) {
                char = input[++current];
                if (char == '{') braceCount++;
                if (char == '}') braceCount--;
                code += char
            }
            return code.slice(0, -1).trim();
        };

        if (inTag) { // 开始标签内属性解析
            // 标签结束
            if (char == '>') {
                inTag = false;
                tokens.push({ type: 'closeTag' })
            }
            // 单闭合标签
            else if (char == '/' && input[current + 1] == '>') {
                inTag = false;
                tokens.push({ type: 'endTag' })
                current++;
            }
            else if (char == '=') {
                tokens.push({ type: 'equals' });
            }
            else if (char == '{') {
                tokens.push({
                    type: 'code',
                    value: getCode()
                })
            }
            else if (WHITESPACE.test(char)) {

            }
            else if (NUMBERS.test(char)) {
                tokens.push({
                    type: 'number',
                    value: Number(getToken(NUMBERS))
                });
                current--;
            }
            else if (NAME.test(char)) {
                const word = getToken(NAME);
                if (word == 'true' || word == 'false') {
                    tokens.push({
                        type: 'boolean',
                        value: word == 'true'
                    });
                } else {
                    tokens.push({
                        type: 'word',
                        value: word
                    });
                }
                current--;
            }
            else if (char == "'") {
                char = input[++current]
                tokens.push({
                    type: 'text',
                    value: getToken(/[^\']/)
                });
            }
            else if (char == '"') {
                char = input[++current]
                tokens.push({
                    type: 'text',
                    value: getToken(/[^\"]/)
                });
            }
        } else {  // 标签外解析
            // 闭合标签
            if (char == '<' && input[current + 1] == '/') {
                char = input[++current]
                char = input[++current]
                tokens.push({
                    type: 'endTag',
                    value: getToken(NAME)
                })
            }
            // 开始标签
            else if (char == '<') {
                inTag = true;
                char = input[++current];
                tokens.push({
                    type: 'openTag',
                    value: getToken(NAME)
                })
                current = current - 1;
            }
            // 内容处理
            else {
                //Handle slush text
                let value = '';
                while (char != '<' && current < input.length) {
                    value += char;
                    current = current + 1;
                    char = input[current];
                }
                value = value.trim()
                if (value) {
                    tokens.push({
                        type: 'text',
                        value: value
                    });
                }
                current = current - 1;
            }
        }
        current = current + 1;
    }
    return tokens;
}

function parser(tokens){
    let nodes = [];
	let current = 0;
	let token = tokens[current];

    // 解析属性
    const parseProps = ()=>{
		let props = {};
		let key = null;
		let last = null;

		while(current < tokens.length && token.type != 'endTag' && token.type != 'closeTag'){
            // 单属性名称
			if(last && token.type == 'word'){
				props[last] = true;
				last = token.value;
			}else if(!key && token.type == 'word'){ //等号左边
				last = token.value;
			}else if(last && token.type == 'equals'){ // = 
				key = last;
				last = null;
			}else if(key && token.type == 'code'){ // onClick="{ddd}"
				props[key] = token.value;
				key = null;
				last = null;
			}else if(key && (token.type == 'number' || token.type == 'text' || token.type == 'boolean')){
				props[key] = token.value;
				key = null;
				last = null;
			}else{
				throw `Invalid property value: ${key}=${token.value}`;
			}
			token = tokens[++current];
		}
		if(last) props[last] = true;
		return props;
	}


    const genNode = (tagType)=>{
		token = tokens[++current];
		return {
			type : tagType,
            // 解析属性
			props : parseProps(),
            // 递归解析子节点
			children : getChildren(tagType)
		};
	};

    const getChildren = (tagType)=>{
		let children = [];
		while(current < tokens.length){
			if(token.type == 'endTag'){ //闭合标签
				if(token.value && token.value != tagType){
					throw `Invalid closing tag: ${token.value}. Expected closing tag of type: ${tagType}`
				}else{
					break;
				}
			}
			if(token.type == 'openTag'){ //标签子元素
				children.push(genNode(token.value));
			}else if(token.type == 'text'){ //文本子元素
				children.push(token.value);
			}
			token = tokens[++current];
		}
		return children;
	}

    const result = getChildren();
	if(result.length == 1) return result[0];
	return result;
}

module.exports = {
    lexer,
    parser
}